﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO;
using System.Globalization;

using BMS.Models;
using BMS.Models.DataAccess;
using BMS.Utilities;

using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;

namespace BMS.Models.BusinessLogic
{
    public class InvoiceDocument
    {
        private String AttachmentTableTemplatePathForDN = Configuration.AttachmentTableTemplatePathForDN;
        private String TemplatePathForDN = Configuration.InvoiceTemplatePathForDN;
        private String TemplatePathForWOOrPO = Configuration.InvoiceTemplatePathForWOOrPO;
        private String TemplatePathForQuo = Configuration.InvoiceTemplatePathForQuo;
        private QuotationRepository QuoRepository = new QuotationRepository();
        private OrderRepository OrderRepository = new OrderRepository();

        public void GenerateInvoice(InvoiceModel invModel, List<InvoiceItemModel> invItemList, FMModel fmModel, CompanyModel companyModel)
        {
            try
            {
                String destPath = Configuration.InvoiceDestinationPath + fmModel.FMName + @"\" + invModel.InvoiceNo + @"\";

                if (Directory.Exists(destPath) == false)
                    Directory.CreateDirectory(destPath);

                String fileName = invModel.InvoiceNo + Configuration.Underscore + "1" + Configuration.Underscore + DateTime.Today.ToString("yyyyMMdd") + Configuration.WordFileFormat;
                String templatePath = TemplatePathForDN;

                if (invModel.isPurchaseOrder == "Y" || invModel.isWorkOrder == "Y")
                    templatePath = TemplatePathForWOOrPO;

                if (invModel.isQuotation == "Y")
                    templatePath = TemplatePathForQuo;

                WordOpenXMLUtil.SaveAsDocx(templatePath, destPath, fileName);
                String destFilePath = destPath + fileName;

                using (WordprocessingDocument oDoc = WordprocessingDocument.Open(destFilePath, true))
                {
                    MainDocumentPart mainPart = oDoc.MainDocumentPart;

                    Paragraph rowTable = null;
                    String tempStrn = "";
                    String tempQuotNo = "", tempInvNo = "";
                    String[] invNoSplit = invModel.InvoiceNo.Split('-');
                    tempInvNo = invNoSplit[1] + Configuration.Hyphen + invNoSplit[2] + Configuration.Hyphen + invNoSplit[3];

                    #region Part I - Header
                    List<HeaderPart> headerList = mainPart.HeaderParts.ToList();
                    HeaderPart header = headerList[0];

                    //foreach (HeaderPart header in mainPart.HeaderParts)
                    //{

                        Header tempHeader = header.Header;
                        SdtBlock quotHeader = header.Header.Descendants<SdtBlock>().Where(r => r.SdtProperties.GetFirstChild<Tag>().Val == "InvoiceHeader").Single();
                        Table quotHeaderTable = quotHeader.Descendants<Table>().Single();
                        List<TableRow> RowsList = quotHeaderTable.Elements<TableRow>().ToList();
                        TableRow tempRow = RowsList[0];
                        String t = "";

                        #region 1st Row - Bill To & Invoice No
                        tempRow.Descendants<TableCell>().ElementAt(1).GetFirstChild<Paragraph>().Remove();
                        rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Left }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(companyModel.CompanyName)));
                        tempRow.Descendants<TableCell>().ElementAt(1).Append(rowTable);

                        tempRow.Descendants<TableCell>().ElementAt(4).GetFirstChild<Paragraph>().Remove();
                        rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Left }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(tempInvNo)));
                        tempRow.Descendants<TableCell>().ElementAt(4).Append(rowTable);
                        #endregion

                        #region 2nd Row - Address 1 & PO No for PO / Date for Quo / Debit Note No for DN
                        tempRow = RowsList[1];
                        tempRow.Descendants<TableCell>().ElementAt(1).GetFirstChild<Paragraph>().Remove();
                        rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Left }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(companyModel.Address1)));
                        tempRow.Descendants<TableCell>().ElementAt(1).Append(rowTable);

                        if (invModel.isPurchaseOrder == "Y")
                        {
                            tempRow.Descendants<TableCell>().ElementAt(4).GetFirstChild<Paragraph>().Remove();
                            rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Left }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                    new Color() { Val = "000000" }, new FontSize() { Val = "18" }), new Text(invModel.PONo)));
                            tempRow.Descendants<TableCell>().ElementAt(4).Append(rowTable);
                        }

                        if (invModel.isQuotation == "Y")
                        {
                            tempRow.Descendants<TableCell>().ElementAt(4).GetFirstChild<Paragraph>().Remove();
                            rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Left }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                    new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(invModel.InvoiceCreationDate.ToString("dd-MMM-yyyy", CultureInfo.CreateSpecificCulture("en-US")))));
                            tempRow.Descendants<TableCell>().ElementAt(4).Append(rowTable);
                        }

                        if (invModel.isDebitNote == "Y")
                        {
                            tempRow.Descendants<TableCell>().ElementAt(4).GetFirstChild<Paragraph>().Remove();
                            rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Left }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                    new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(invModel.DNNo)));
                            tempRow.Descendants<TableCell>().ElementAt(4).Append(rowTable);
                        }
                        #endregion

                        #region 3rd Row - Address 2 & WO No for WO / Ref for Quo / Date for DN
                        tempRow = RowsList[2];
                        tempRow.Descendants<TableCell>().ElementAt(1).GetFirstChild<Paragraph>().Remove();
                        rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Left }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(companyModel.Address2)));
                        tempRow.Descendants<TableCell>().ElementAt(1).Append(rowTable);

                        if (invModel.isWorkOrder == "Y")
                        {
                            tempRow.Descendants<TableCell>().ElementAt(4).GetFirstChild<Paragraph>().Remove();
                            rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Left }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                    new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(invModel.WONo)));
                            tempRow.Descendants<TableCell>().ElementAt(4).Append(rowTable);
                        }

                        if (invModel.isQuotation == "Y")
                        {
                            tempQuotNo = invModel.QuotNo;
                            tempRow.Descendants<TableCell>().ElementAt(4).GetFirstChild<Paragraph>().Remove();
                            rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Left }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                    new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(tempQuotNo.Replace("Q-", ""))));
                            tempRow.Descendants<TableCell>().ElementAt(4).Append(rowTable);
                        }

                        if (invModel.isDebitNote == "Y")
                        {
                            tempRow.Descendants<TableCell>().ElementAt(4).GetFirstChild<Paragraph>().Remove();
                            rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Left }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                    new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(invModel.InvoiceCreationDate.ToString("dd-MMM-yyyy", CultureInfo.CreateSpecificCulture("en-US")))));
                            tempRow.Descendants<TableCell>().ElementAt(4).Append(rowTable);
                        }
                        #endregion

                        #region 4th Row - Address 3 & Ref for WO / PO / Vendor No for DN
                        tempRow = RowsList[3];
                        tempRow.Descendants<TableCell>().ElementAt(1).GetFirstChild<Paragraph>().Remove();
                        rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Left }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(companyModel.Address3)));
                        tempRow.Descendants<TableCell>().ElementAt(1).Append(rowTable);

                        if (invModel.isWorkOrder == "Y" || invModel.isPurchaseOrder == "Y")
                        {

                            if (invModel.isPurchaseOrder == "Y")
                                tempQuotNo = QuoRepository.GetQuotationByPONo(invModel.PONo).QuotationNo;

                            if (invModel.isWorkOrder == "Y")
                                tempQuotNo = OrderRepository.GetOrderByWONo(invModel.WONo).QuotationNo;

                            tempRow.Descendants<TableCell>().ElementAt(4).GetFirstChild<Paragraph>().Remove();
                            rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Left }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                    new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(tempQuotNo.Replace("Q-", ""))));
                            tempRow.Descendants<TableCell>().ElementAt(4).Append(rowTable);
                        }

                        if (invModel.isDebitNote == "Y")
                        {
                            tempRow.Descendants<TableCell>().ElementAt(4).GetFirstChild<Paragraph>().Remove();
                            rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Left }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                    new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(Configuration.VendorNo)));
                            tempRow.Descendants<TableCell>().ElementAt(4).Append(rowTable);
                        }
                        #endregion

                        #region 5th Row - Address 4 & Date for WO / PO
                        tempRow = RowsList[4];
                        tempRow.Descendants<TableCell>().ElementAt(1).GetFirstChild<Paragraph>().Remove();
                        rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Left }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(companyModel.Address4)));
                        tempRow.Descendants<TableCell>().ElementAt(1).Append(rowTable);

                        if (invModel.isWorkOrder == "Y" || invModel.isPurchaseOrder == "Y")
                        {
                            tempRow.Descendants<TableCell>().ElementAt(4).GetFirstChild<Paragraph>().Remove();
                            rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Left }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                    new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(invModel.InvoiceCreationDate.ToString("dd-MMM-yyyy", CultureInfo.CreateSpecificCulture("en-US")))));
                            tempRow.Descendants<TableCell>().ElementAt(4).Append(rowTable);
                        }
                        #endregion

                        #region 6th Row - Tel & Vendor No
                        tempRow = RowsList[5];
                        tempRow.Descendants<TableCell>().ElementAt(1).GetFirstChild<Paragraph>().Remove();
                        rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Left }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(companyModel.TelephoneNo)));
                        tempRow.Descendants<TableCell>().ElementAt(1).Append(rowTable);

                        if (invModel.isWorkOrder == "Y" || invModel.isPurchaseOrder == "Y")
                        {
                            tempRow.Descendants<TableCell>().ElementAt(4).GetFirstChild<Paragraph>().Remove();
                            rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Left }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                    new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(Configuration.VendorNo)));
                            tempRow.Descendants<TableCell>().ElementAt(4).Append(rowTable);
                        }
                        #endregion

                        #region 7th Row - Fax
                        tempRow = RowsList[6];
                        tempRow.Descendants<TableCell>().ElementAt(1).GetFirstChild<Paragraph>().Remove();
                        rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Left }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(companyModel.FaxNo)));
                        tempRow.Descendants<TableCell>().ElementAt(1).Append(rowTable);
                        #endregion

                        #region 8th Row - Attention To
                        tempRow = RowsList[7];
                        tempRow.Descendants<TableCell>().ElementAt(1).GetFirstChild<Paragraph>().Remove();
                        rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Left }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(fmModel.AttentionTo)));
                        tempRow.Descendants<TableCell>().ElementAt(1).Append(rowTable);
                        #endregion
                    //}

                    #endregion

                    #region Part II - Invoice Content
                    SdtBlock ccWithTable = mainPart.Document.Body.Descendants<SdtBlock>().Where(r => r.SdtProperties.GetFirstChild<Tag>().Val == "PaymentTable").Single();
                    Table table = ccWithTable.Descendants<Table>().Single();
                    List<TableRow> rowList = table.Elements<TableRow>().ToList();
                    TableRow row = rowList[6];

                    #region 6th Row - 100 % Completion Amount
                    tempStrn = "HK$ " + invModel.TotalAmount.ToString("#,##0.00");
                    row.Descendants<TableCell>().ElementAt(1).GetFirstChild<Paragraph>().Remove();
                    rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Right }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                            new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(tempStrn)));
                    row.Descendants<TableCell>().ElementAt(1).Append(rowTable);
                    #endregion

                    #region 8th Row - Total Amount
                    row = rowList[8];
                    tempStrn = "HK$ " + invModel.TotalAmount.ToString("#,##0.00");
                    row.Descendants<TableCell>().ElementAt(1).GetFirstChild<Paragraph>().Remove();
                    rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Right }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                            new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(tempStrn)));
                    row.Descendants<TableCell>().ElementAt(1).Append(rowTable);
                    #endregion

                    tempStrn = "** Say Hong Kong Dollars " + NumberUtil.changeCurrencyToWords((double)invModel.TotalAmount) + " **";
                    mainPart.Document.Descendants<SdtElement>().Where(r => r.SdtProperties.GetFirstChild<Tag>().Val == "TotalAmountInWord").Single().Descendants<Text>().First().Text = tempStrn;

                    if (invModel.isPurchaseOrder == "Y" || invModel.isWorkOrder == "Y" || invModel.isQuotation == "Y")
                    {
                        OrderModel orderModel = OrderRepository.GetOrder(tempQuotNo);
                        tempStrn = orderModel.Location + Configuration.Space + Configuration.Hyphen + Configuration.Space + orderModel.Description;

                        if (orderModel.Description == "" || orderModel.Description == null)
                            tempStrn = orderModel.Location;

                        mainPart.Document.Descendants<SdtElement>().Where(r => r.SdtProperties.GetFirstChild<Tag>().Val == "LocationWithDescription").Single().Descendants<Text>().First().Text = tempStrn;
                    }
                    else if (invModel.isDebitNote == "Y")
                    {
                        mainPart.Document.Descendants<SdtElement>().Where(r => r.SdtProperties.GetFirstChild<Tag>().Val == "DebitNoteNo1").Single().Descendants<Text>().First().Text = invModel.DNNo;
                        mainPart.Document.Descendants<SdtElement>().Where(r => r.SdtProperties.GetFirstChild<Tag>().Val == "DebitNoteNo2").Single().Descendants<Text>().First().Text = invModel.DNNo;
                    }

                    String[] invoiceNoSplit = tempInvNo.Split('-');
                    tempStrn = invoiceNoSplit[0] + Configuration.Hyphen + invoiceNoSplit[2];

                    mainPart.Document.Descendants<SdtElement>().Where(r => r.SdtProperties.GetFirstChild<Tag>().Val == "InvoiceNo").Single().Descendants<Text>().First().Text = tempStrn;

                    #region Purchase Order Or Work Order
                    if (invModel.isPurchaseOrder == "Y" || invModel.isWorkOrder == "Y")
                    {
                        if (invModel.isWorkOrder == "Y")
                        {
                            mainPart.Document.Descendants<SdtElement>().Where(r => r.SdtProperties.GetFirstChild<Tag>().Val == "POOrWO").Single().Descendants<Text>().First().Text = "Work Order";
                            mainPart.Document.Descendants<SdtElement>().Where(r => r.SdtProperties.GetFirstChild<Tag>().Val == "WOOrPONo").Single().Descendants<Text>().First().Text = invModel.WONo;
                        }

                        if (invModel.isPurchaseOrder == "Y")
                        {
                            mainPart.Document.Descendants<SdtElement>().Where(r => r.SdtProperties.GetFirstChild<Tag>().Val == "POOrWO").Single().Descendants<Text>().First().Text = "Purchase Order";
                            mainPart.Document.Descendants<SdtElement>().Where(r => r.SdtProperties.GetFirstChild<Tag>().Val == "WOOrPONo").Single().Descendants<Text>().First().Text = invModel.PONo;
                        }
                    }
                    #endregion

                    #region Quotation
                    if(invModel.isQuotation == "Y")
                        mainPart.Document.Descendants<SdtElement>().Where(r => r.SdtProperties.GetFirstChild<Tag>().Val == "QuotationNo").Single().Descendants<Text>().First().Text = tempQuotNo.Replace("Q-", "");
                    #endregion

                    #endregion
                }

                //#region PDF Conversion
                //String srcFilePath = destFilePath;
                //destFilePath = srcFilePath.Replace(".docx", ".pdf");

                //PDFUtil.WordToPDF(srcFilePath, destFilePath);
                //#endregion
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public void GenerateAttachmentTable(InvoiceModel invModel, List<InvoiceItemModel> invItemList, FMModel fmModel, CompanyModel companyModel)
        {
            try
            {
                String destPath = Configuration.InvoiceDestinationPath + fmModel.FMName + @"\" + invModel.InvoiceNo + @"\";

                if (Directory.Exists(destPath) == false)
                    Directory.CreateDirectory(destPath);

                String fileName = invModel.InvoiceNo + Configuration.Underscore + "2" + Configuration.Underscore + DateTime.Today.ToString("yyyyMMdd") + Configuration.WordFileFormat;

                WordOpenXMLUtil.SaveAsDocx(AttachmentTableTemplatePathForDN, destPath, fileName);
                String destFilePath = destPath + fileName;

                using (WordprocessingDocument oDoc = WordprocessingDocument.Open(destFilePath, true))
                {
                    MainDocumentPart mainPart = oDoc.MainDocumentPart;

                    Paragraph rowTable = null;
                    String tempStrn = "";
                    String tempQuotNo = "";
                     
                    #region Part I - Header
                    List<HeaderPart> headerList = mainPart.HeaderParts.ToList();

                    //foreach (HeaderPart header in mainPart.HeaderParts)
                    for (int i = 0; i < headerList.Count; i++)
                    {
                        if (i == 0)
                        {
                            Header tempHeader = headerList[i].Header;
                            SdtBlock quotHeader = headerList[i].Header.Descendants<SdtBlock>().Where(r => r.SdtProperties.GetFirstChild<Tag>().Val == "InvoiceHeader").Single();
                            Table quotHeaderTable = quotHeader.Descendants<Table>().Single();
                            List<TableRow> RowsList = quotHeaderTable.Elements<TableRow>().ToList();
                            TableRow tempRow = RowsList[0];
                            String t = "";

                            #region 1st Row - Bill To & Debit Note No
                            tempRow.Descendants<TableCell>().ElementAt(1).GetFirstChild<Paragraph>().Remove();
                            rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Left }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                    new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(companyModel.CompanyName)));
                            tempRow.Descendants<TableCell>().ElementAt(1).Append(rowTable);

                            tempRow.Descendants<TableCell>().ElementAt(4).GetFirstChild<Paragraph>().Remove();
                            rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Left }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                    new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(invModel.DNNo)));
                            tempRow.Descendants<TableCell>().ElementAt(4).Append(rowTable);
                            #endregion

                            #region 2nd Row - Attention To & Invoice Date
                            tempRow = RowsList[1];
                            tempRow.Descendants<TableCell>().ElementAt(1).GetFirstChild<Paragraph>().Remove();
                            rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Left }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                    new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(fmModel.AttentionTo)));
                            tempRow.Descendants<TableCell>().ElementAt(1).Append(rowTable);

                            tempRow.Descendants<TableCell>().ElementAt(4).GetFirstChild<Paragraph>().Remove();
                            rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Left }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                    new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(invModel.InvoiceCreationDate.ToString("dd-MMM-yyyy", CultureInfo.CreateSpecificCulture("en-US")))));
                            tempRow.Descendants<TableCell>().ElementAt(4).Append(rowTable);
                            #endregion
                        }
                    }

                    #endregion

                    #region Part II - Invoice Attachment Content
                    int currentTable = 1;
                    int NoOfPagesRequired = GetNoOfPages(invItemList);
                    SdtBlock emptyElement = (SdtBlock)mainPart.Document.Descendants<SdtElement>().Where(r => r.SdtProperties.GetFirstChild<Tag>().Val == "InvoiceItemTable_1").Single().Clone();
                    SdtBlock copyBlock = new SdtBlock();

                    for (int i = 0; i < NoOfPagesRequired; i++)
                    {
                        String tempTableTag = "InvoiceItemTable_" + currentTable;

                        #region Additional Table
                        if (currentTable < NoOfPagesRequired && currentTable != NoOfPagesRequired)
                        {
                            SdtBlock lastElement = (SdtBlock)mainPart.Document.Descendants<SdtElement>().Where(r => r.SdtProperties.GetFirstChild<Tag>().Val == tempTableTag).Single();
                            copyBlock = emptyElement;
                            copyBlock.SdtProperties.GetFirstChild<Tag>().Val = "InvoiceItemTable_" + (currentTable + 1);

                            // Insert a blank new page
                            Run run = new Run(new Break() { Type = BreakValues.Page });
                            Paragraph para = new Paragraph(run);
                            SdtProperties sdtPr = new SdtProperties(new SdtAlias { Val = "NewPage" }, new Tag { Val = "NewPage" + currentTable });
                            SdtContentBlock sdtCBlock = new SdtContentBlock(para);
                            SdtBlock sdtBlock = new SdtBlock(sdtPr, sdtCBlock);
                            lastElement.InsertAfterSelf(sdtBlock);

                            sdtBlock.InsertAfterSelf(copyBlock);
                        }
                        #endregion

                        SdtBlock ccWithTable = mainPart.Document.Body.Descendants<SdtBlock>().Where(r => r.SdtProperties.GetFirstChild<Tag>().Val == tempTableTag).Single();
                        Table table = ccWithTable.Descendants<Table>().Single();
                        TableRow row = table.Elements<TableRow>().Last();
                        TableRow emptyRow = table.Elements<TableRow>().Last();
                        TableRow rowCopy = null;

                        int currentItemNo = 1;
                        decimal CarryForward = 0;

                        int SIndex = GetStartIndex(i);
                        int EIndex = GetEndIndex(invItemList, currentTable, NoOfPagesRequired);
                        List<InvoiceItemModel> tempList = GetRequiredItemModel(invItemList, SIndex, EIndex);

                        #region Items
                        foreach(InvoiceItemModel item in tempList)
                        {
                            OrderModel tempOrder = OrderRepository.GetOrder(item.QuotationNo);
                            QuotationModel tempQuo = QuoRepository.GetQuotation(item.QuotationNo);

                            // Copy the blank row
                            rowCopy = (TableRow)row.Clone();
                            row.Descendants<TableCell>().ElementAt(0).GetFirstChild<Paragraph>().Remove();
                            rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Center }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                    new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(item.QuotationNo.Replace("Q-", ""))));
                            row.Descendants<TableCell>().ElementAt(0).Append(rowTable);
                            row.Descendants<TableCell>().ElementAt(1).GetFirstChild<Paragraph>().Remove();
                            rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Left }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                    new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(tempOrder.Location)));
                            row.Descendants<TableCell>().ElementAt(1).Append(rowTable);
                            row.Descendants<TableCell>().ElementAt(2).GetFirstChild<Paragraph>().Remove();
                            tempStrn = tempOrder.WorkOrderNo;
                            if (tempOrder.WorkOrderNo == "" || tempOrder.WorkOrderNo == null)
                                tempStrn = tempQuo.PONo;
                            rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Center }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                    new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(tempStrn)));
                            row.Descendants<TableCell>().ElementAt(2).Append(rowTable);
                            row.Descendants<TableCell>().ElementAt(3).GetFirstChild<Paragraph>().Remove();

                            if (tempQuo.WorkCompletionDate.Value != DateTime.MinValue)
                            {
                                rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Center }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                    new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(tempQuo.WorkCompletionDate.Value.ToString("dd-MMM-yyyy", CultureInfo.CreateSpecificCulture("en-US")))));
                            }
                            else
                            {
                                rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Center }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                    new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text("")));
                            }
                            row.Descendants<TableCell>().ElementAt(3).Append(rowTable);
                            row.Descendants<TableCell>().ElementAt(4).GetFirstChild<Paragraph>().Remove();
                            rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Right }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                    new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text(tempQuo.TotalAmount.ToString("#,##0.00"))));
                            row.Descendants<TableCell>().ElementAt(4).Append(rowTable);

                            if (currentItemNo != tempList.Count)
                                table.AppendChild(rowCopy);

                            row = table.Elements<TableRow>().Last();
                            currentItemNo++;
                        }
                        #endregion

                        if (currentTable == NoOfPagesRequired)
                        {
                            #region Part d - last Row
                            row = table.Elements<TableRow>().Last();
                            rowCopy = (TableRow)row.Clone();
                            table.AppendChild(rowCopy);

                            row = table.Elements<TableRow>().Last();
                            TableCellProperties tcp1 = new TableCellProperties();
                            tcp1 = new TableCellProperties(new TableCellBorders(new TableCellProperties(new LeftBorder() { Val = BorderValues.Nil }
                                , new RightBorder() { Val = BorderValues.Nil }, new BottomBorder() { Val = BorderValues.Nil }, new TopBorder() { Val = BorderValues.Nil })));

                            #region Last Row
                            String text = "Total Amount :", text2 = invModel.TotalAmount.ToString("#,##0.00");
                            tcp1 = new TableCellProperties();
                            tcp1 = new TableCellProperties(new TableCellBorders(new TableCellProperties(new LeftBorder() { Val = BorderValues.Nil }
                                , new RightBorder() { Val = BorderValues.Nil }, new BottomBorder() { Val = BorderValues.Nil }, new TopBorder() { Val = BorderValues.Nil })));
                            row.Descendants<TableCell>().ElementAt(0).GetFirstChild<Paragraph>().Remove();
                            rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Center }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                    new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text("")));
                            row.Descendants<TableCell>().ElementAt(0).Append(tcp1);
                            row.Descendants<TableCell>().ElementAt(0).Append(rowTable);
                            tcp1 = new TableCellProperties();
                            tcp1 = new TableCellProperties(new TableCellBorders(new TableCellProperties(new LeftBorder() { Val = BorderValues.Nil }
                                , new RightBorder() { Val = BorderValues.Nil }, new BottomBorder() { Val = BorderValues.Nil }, new TopBorder() { Val = BorderValues.Nil })));
                            row.Descendants<TableCell>().ElementAt(1).GetFirstChild<Paragraph>().Remove();
                            rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Center }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                    new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text("")));
                            row.Descendants<TableCell>().ElementAt(1).Append(tcp1);
                            row.Descendants<TableCell>().ElementAt(1).Append(rowTable);
                            tcp1 = new TableCellProperties();
                            tcp1 = new TableCellProperties(new TableCellBorders(new TableCellProperties(new LeftBorder() { Val = BorderValues.Nil }
                                , new RightBorder() { Val = BorderValues.Nil }, new BottomBorder() { Val = BorderValues.Nil }, new TopBorder() { Val = BorderValues.Nil })));
                            row.Descendants<TableCell>().ElementAt(2).GetFirstChild<Paragraph>().Remove();
                            rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Center }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                    new Color() { Val = "000000" }, new FontSize() { Val = "20" }), new Text("")));
                            row.Descendants<TableCell>().ElementAt(2).Append(tcp1);
                            row.Descendants<TableCell>().ElementAt(2).Append(rowTable);
                            tcp1 = new TableCellProperties();
                            tcp1 = new TableCellProperties(new TableCellBorders(new TableCellProperties(new LeftBorder() { Val = BorderValues.Nil }
                                , new RightBorder() { Val = BorderValues.Nil }, new BottomBorder() { Val = BorderValues.Nil }, new TopBorder() { Val = BorderValues.Nil })));
                            row.Descendants<TableCell>().ElementAt(3).GetFirstChild<Paragraph>().Remove();
                            rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Right }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                    new Color() { Val = "000000" }, new Bold(), new FontSize() { Val = "20" }), new Text(text)));
                            row.Descendants<TableCell>().ElementAt(3).Append(tcp1);
                            row.Descendants<TableCell>().ElementAt(3).Append(rowTable);
                            tcp1 = new TableCellProperties();
                            tcp1 = new TableCellProperties(new TableCellBorders(new TableCellProperties(new LeftBorder() { Val = BorderValues.Nil }
                                , new RightBorder() { Val = BorderValues.Nil }, new BottomBorder() { Val = BorderValues.Double }, new TopBorder() { Val = BorderValues.Nil })));
                            row.Descendants<TableCell>().ElementAt(4).GetFirstChild<Paragraph>().Remove();
                            rowTable = new Paragraph(new ParagraphProperties(new Justification() { Val = JustificationValues.Right }), new Run(new RunProperties(new RunFonts() { Ascii = "Arial" },
                                    new Color() { Val = "000000" }, new Bold(), new FontSize() { Val = "20" }), new Text(text2)));
                            row.Descendants<TableCell>().ElementAt(4).Append(tcp1);
                            row.Descendants<TableCell>().ElementAt(4).Append(rowTable);
                            #endregion
                            #endregion
                        }

                        currentTable++;
                    }
                    #endregion
                }

                //#region PDF Conversion
                //String srcFilePath = destFilePath;
                //destFilePath = srcFilePath.Replace(".docx", ".pdf");

                //PDFUtil.WordToPDF(srcFilePath, destFilePath);
                //#endregion

                //#region Combine PDF files
                //String[] PDFFiles = Directory.GetFiles(destPath, "*.pdf");
                //String outputFilePath = destPath + invModel.InvoiceNo + Configuration.Underscore + DateTime.Today.ToString("yyyyMMdd") + Configuration.PDFFileFormat;
                //PDFUtil.MergePDFs(outputFilePath, PDFFiles);

                ////WordOpenXMLUtil.DeleteFiles(PDFFiles);
                //#endregion
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        private int GetNoOfPages(List<InvoiceItemModel> invItemList)
        {
            double NoOfPages = (double)((double)invItemList.Count / (double)Configuration.MaxNoOfItemsForInvoice);
            return (int)Math.Ceiling(NoOfPages);
        }

        private int GetStartIndex(int currentPageNo)
        {
            int resultIndex = currentPageNo * Configuration.MaxNoOfRecords;
            return resultIndex;
        }

        private int GetEndIndex(List<InvoiceItemModel> invItemList, int currPageNo, int noOfPage)
        {
            int resultIndex = (currPageNo * Configuration.MaxNoOfItemsForInvoice) - 1;

            if (currPageNo == noOfPage)
                resultIndex = invItemList.Count - 1;

            return resultIndex;
        }

        private List<InvoiceItemModel> GetRequiredItemModel(List<InvoiceItemModel> invItemList, int SIndex, int EIndex)
        {
            List<InvoiceItemModel> resultList = new List<InvoiceItemModel>();

            for (int i = SIndex; i <= EIndex; i++)
                resultList.Add(invItemList[i]);

            return resultList;
        }
    }
}